/**
 * @file dxWatchdog.js
 * @module dxWatchdog
 * @description
 * Watchdog module based on the native watchdog C library.
 * This module provides a handle-based interface for watchdog operations,
 * including software watchdog and hardware watchdog support.
 *
 * It is designed for high-performance, multi-threaded environments, allowing different
 * watchdog instances to be operated in parallel safely.
 *
 * @usage
 * // 1. Import the module
 * import watchdog from 'dxWatchdog.js';
 *
 * // 2. Init the watchdog (single instance)
 * try {
 *   watchdog.init();
 * } catch (e) {
 *   logger.error("Failed to init watchdog:", e);
 * }
 *
 * try {
 *   // 3. Start the watchdog timer with a timeout of 5000ms
 *   const started = watchdog.start(5000);
 *   logger.info("Watchdog started:", started);
 *
 *   // 4. Check if watchdog is powered on
 *   const isPoweron = watchdog.isPoweron();
 *   logger.info("Watchdog is poweron:", isPoweron);
 *
 *   // 5. Restart the watchdog timer for channel 0
 *   const restarted = watchdog.restart(0);
 *   logger.info("Watchdog restarted:", restarted);
 *
 *   // 6. Enable channel 0
 *   const enabled = watchdog.enable(0, true);
 *   logger.info("Channel enabled:", enabled);
 *
 *   // 7. Stop the watchdog timer
 *   watchdog.stop();
 * } catch (e) {
 *   console.error("Watchdog operation failed:", e);
 * }
 *
 * // 8. Deinit the watchdog when done
 * watchdog.deinit();
 */
import { watchdog as nativeWatchdog } from './libvbar-m-dxwatchdog.so'

const watchdog = {}

/**
 * @readonly
 * @enum {number}
 * Watchdog type enumeration.
 */
watchdog.TYPE = Object.freeze({
	SOFTWARE: 1,  // Software watchdog
	HARDWARE: 2,  // Hardware watchdog
});

/**
 * Initializes a watchdog device and returns its handle.
 * @throws {Error} If the watchdog fails to init or if parameters are invalid.
 */
watchdog.init = function () {
	try {
		nativeWatchdog.init();
	} catch (e) {
		// The C layer throws an exception on failure. We catch it and re-throw a more user-friendly JS error.
		throw new Error(`watchdog.init: failed to init watchdog. Reason: ${e.message}`);
	}
}

/**
 * Deinits the watchdog device.
 * @returns {boolean} Always returns true on success.
 */
watchdog.deinit = function () {
	return nativeWatchdog.deinit()
}

/**
 * Checks if the watchdog device is powered on.
 * @returns {boolean} True if the device is powered on, false otherwise.
 */
watchdog.isPoweron = function () {
	return nativeWatchdog.isPoweron()
}

/**
 * Starts the watchdog timer.
 * @param {number} timeout_ms - The timeout in milliseconds. Must be greater than 0.
 * @returns {boolean} True on success, false on failure.
 * @throws {Error} If timeout_ms is invalid.
 */
watchdog.start = function (timeout_ms) {
	if (timeout_ms === undefined || timeout_ms === null) {
		throw new Error("watchdog.start: 'timeout_ms' parameter is required.")
	}
	if (timeout_ms <= 0) {
		throw new Error("watchdog.start: 'timeout_ms' must be greater than 0.")
	}
	return nativeWatchdog.start(timeout_ms)
}

/**
 * Stops the watchdog timer.
 */
watchdog.stop = function () {
	nativeWatchdog.stop()
}

/**
 * Enables or disables a specific channel of the watchdog.
 * @param {number} chan - The channel number to enable/disable.
 * @param {boolean} toset - True to enable the channel, false to disable it.
 * @returns {boolean} True on success, false on failure.
 */
watchdog.enable = function (chan = 0, toset = true) {
	if (chan === undefined || chan === null) {
		throw new Error("watchdog.enable: 'chan' parameter is required.")
	}
	return nativeWatchdog.enable(chan, toset)
}

/**
 * Restarts the watchdog timer for a specific channel.
 * @param {number} chan - The channel number to restart.
 * @returns {boolean} True on success, false on failure.
 */
watchdog.restart = function (chan = 0) {
	if (chan === undefined || chan === null) {
		throw new Error("watchdog.restart: 'chan' parameter is required.")
	}
	return nativeWatchdog.restart(chan)
}

export default watchdog;
